package live.jialing.sip.base.service;

import com.google.common.collect.Lists;
import live.jialing.authz.domain.SecurityGroup;
import live.jialing.authz.domain.SecurityGroupUser;
import live.jialing.authz.service.AuthorizationService;
import live.jialing.authz.service.SecurityGroupService;
import live.jialing.core.data.LinkType;
import live.jialing.core.data.jpa.CustomJpaRepository;
import live.jialing.core.exception.ServiceException;
import live.jialing.core.service.BaseDomainService;
import live.jialing.core.service.GeneralService;
import live.jialing.data.util.SpecificationUtil;
import live.jialing.sip.base.dict.SchoolRoleEnum;
import live.jialing.sip.base.dict.SchoolTitleEnum;
import live.jialing.sip.base.domain.School;
import live.jialing.sip.base.domain.Squad;
import live.jialing.sip.base.domain.Teacher;
import live.jialing.sip.base.repository.TeacherRepository;
import live.jialing.structure.domain.Employee;
import live.jialing.util.general.Collections3;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 老师
 */
@Service
public class TeacherService extends BaseDomainService<Teacher, Long> implements GeneralService<Teacher, Long> {

    private static Logger logger = LoggerFactory.getLogger(TeacherService.class);

    @Resource
    private TeacherRepository teacherRepository;

    @Resource
    private SecurityGroupService securityGroupService;

    @Resource
    private AuthorizationService authorizationService;

    @Override
    public CustomJpaRepository getRepository() {
        return this.teacherRepository;
    }

    public Specification<Teacher> buildSpecification(Class<Teacher> classz, Map<String, Object> searchParams, LinkType type) {

        return SpecificationUtil.buildSpecification(classz, searchParams, type);
    }

    /**
     * 设置班主任<br>
     * 每个班的班主任只能有一个
     *
     * @param schoolId   学校ID
     * @param classId    班级ID
     * @param employeeId 员工ID
     */
    @Transactional
    public void setupClassMaster(long schoolId, long classId, long employeeId) {

        if (schoolId < 1 || classId < 2000 || employeeId < 1) {
            logger.warn("参数错误：schoolId={},classId={},teacherId={}", schoolId, classId, employeeId);
            return;
        }

        List<Teacher> classTeacherRelations = teacherRepository.findByClassIdAndTitle(classId, SchoolTitleEnum.CLS_MASTER.toString());
        if (!Collections3.isEmpty(classTeacherRelations)) {
            throw new ServiceException("该班级中已经存在班主任，每个班只能有一个班主任！");
        }

        Squad cls = new Squad();
        cls.setId(classId);

        School sch = new School();
        sch.setId(schoolId);

        Employee empl = new Employee();
        empl.setId(employeeId);

        // 班级关联教职工，不设置科目
        Teacher teacher = new Teacher();
        teacher.setSchool(sch);
        teacher.setSquad(cls);
        teacher.setEmployee(empl);
        teacher.setTitle(SchoolTitleEnum.CLS_MASTER.toString());
        this.add(teacher);

        // 设置为班主任角色
        SecurityGroup securityGroup = securityGroupService.findSecurityGroupInOrgByCode(schoolId, SchoolRoleEnum.SCH_CLS_MASTER.toString());
        securityGroupService.setupUsers(securityGroup.getId(), classId, Lists.newArrayList(employeeId));
    }

    /**
     * 更新班主任
     *
     * @param teacherId    老师ID
     * @param schoolId     学校ID
     * @param classId      班级ID
     * @param newEmplyeeId 新员工工id
     */
    @Transactional
    public void updateClassMaster(long teacherId, long schoolId, long classId, long newEmplyeeId) {

        // 获取old的记录
        List<Teacher> teachers = teacherRepository.findByClassIdAndTitle(classId, SchoolTitleEnum.CLS_MASTER.toString());

        if (Collections3.isEmpty(teachers)) {
            throw new ServiceException("找不到班主任记录");
        }
        if (Long.compare(teachers.get(0).getId(), teacherId) != 0) {
            throw new ServiceException("传入的老师ID与班级中的班主任ID不一致");
        }

        // 教职工一致时，不需要处理
        if (Long.compare(teachers.get(0).getEmployee().getId(), newEmplyeeId) == 0) {
            return;
        }

        // 更新班级中的成员
        Teacher classMaster = teachers.get(0);
        Employee employee = new Employee();
        employee.setId(newEmplyeeId);
        classMaster.setEmployee(employee);
        this.edit(classMaster);

        // 移除班主任角色
        List<SecurityGroupUser> securityGroupUsers = authorizationService.findSecurityGroupUserByCode(classId, SchoolRoleEnum.SCH_CLS_MASTER.toString());
        securityGroupService.removeUsers(securityGroupUsers.get(0).getSecurityGroupId(), classId,
                securityGroupUsers.stream().map(sgu -> sgu.getUserId()).distinct().collect(Collectors.toList()));
        // 新增班主任角色
        securityGroupService.setupUsers(securityGroupUsers.get(0).getSecurityGroupId(), classId, Lists.newArrayList(newEmplyeeId));

    }

    /**
     * 设置班级中任课老师<br>
     * 每个科目只能有一个任课老师
     *
     * @param schoolId   学校ID
     * @param classId    班级ID
     * @param employeeId 教职工ID
     * @param subject    科目
     */
    @Transactional
    public void setupClassTeacher(long schoolId, long classId, long employeeId, String subject) {

        if (schoolId < 1 || classId < 2000 || employeeId < 1 || StringUtils.isBlank(subject)) {
            logger.warn("参数错误：schoolId={},classId={},teacherId={},subject={}", schoolId, classId, employeeId, subject);
            return;
        }

        Teacher ctr = teacherRepository.findByClassIdAndSubject(classId, subject);
        if (ctr != null) {
            throw new ServiceException("班级中科目已经设置了任课老师，一个科目只能设置一位任课老师");
        }

        // 班级关联教职工，设置科目
        Squad cls = new Squad();
        cls.setId(classId);
        School sch = new School();
        sch.setId(schoolId);
        Employee employee = new Employee();
        employee.setId(employeeId);
        Teacher teacher = new Teacher();
        teacher.setSchool(sch);
        teacher.setSquad(cls);
        teacher.setEmployee(employee);
        teacher.setTitle(SchoolTitleEnum.CLS_TEACHER.toString());
        teacher.setSubject(subject);
        this.add(teacher);

        // 设置为任课老师角色
        List<SecurityGroupUser> securityGroupUsers = authorizationService.findSecurityGroupUserByUser(classId, employeeId);
        Optional<SecurityGroupUser> classTeacher = securityGroupUsers.stream()
                .filter(sgu -> StringUtils.equals(sgu.getSecurityGroupCode(), SchoolRoleEnum.SCH_CLS_TEACHER.toString()))
                .findAny();
        if (!classTeacher.isPresent()) {
            // 还不是班级任课老师角色
            SecurityGroup securityGroup = securityGroupService.findSecurityGroupInOrgByCode(schoolId, SchoolRoleEnum.SCH_CLS_TEACHER.toString());
            securityGroupService.setupUsers(securityGroup.getId(), classId, Lists.newArrayList(employeeId));
        }
    }

    /**
     * 更新班级中任课老师<br>
     *
     * @param teacherId     任课老师ID
     * @param schoolId      学校ID
     * @param classId       班级ID
     * @param newEmployeeId 员工ID
     */
    @Transactional
    public void updateClassTeacher(long teacherId, long schoolId, long classId, long newEmployeeId) {

        if (schoolId < 1 || classId < 2000 || newEmployeeId < 1) {
            logger.warn("参数错误：teacherId={},schoolId={},classId={},teacherId={}", teacherId, schoolId, classId, newEmployeeId);
            return;
        }

        Teacher oldCtr = teacherRepository.findOne(teacherId);
        if (oldCtr == null) {
            throw new ServiceException("系统中无此记录");
        }
        // 更新班级关联教职工，设置科目
        Teacher classTeacherRelation = new Teacher();
        Employee employee = new Employee();
        employee.setId(newEmployeeId);
        oldCtr.setEmployee(employee);
        this.edit(classTeacherRelation);

        // 判断老教职工在班级中的情况
        // 1、只有一条任课老师
        // 2、有多条任课老师
        // 3、有一条任课老师+其他角色
        // 4、有多条任课老师+其他角色
        // 5、无任课老师角色，有其他的角色
        List<Teacher> classTeacherRelations = teacherRepository.findByClassIdAndTeacherIdAndTitle(classId, oldCtr.getEmployee().getId(), SchoolTitleEnum.CLS_TEACHER.toString());
        // 处理只有一条任课老师的情况，去掉老任课老师的任课老师角色
        if (!Collections3.isEmpty(classTeacherRelations) && classTeacherRelations.size() == 1) {
            // 得到老任课老师在班中所有的角色
            List<SecurityGroupUser> securityGroupUsers = authorizationService.findSecurityGroupUserByUser(classId, oldCtr.getEmployee().getId());
            // 得到任课老师的角色
            Optional<SecurityGroupUser> securityGroupUser = securityGroupUsers.stream()
                    .filter(sgu -> StringUtils.equals(sgu.getSecurityGroupCode(), SchoolRoleEnum.SCH_CLS_TEACHER.toString()))
                    .findFirst();
            // 去除任课老师的角色
            securityGroupService.removeUsers(securityGroupUser.get().getSecurityGroupId(), classId,
                    Lists.newArrayList(securityGroupUser.get().getUserId()));
        }

        // 设置新任课老师的角色
        List<SecurityGroupUser> securityGroupUsers = authorizationService.findSecurityGroupUserByUser(classId, newEmployeeId);
        if (!Collections3.isEmpty(securityGroupUsers)) {
            Optional<SecurityGroupUser> securityGroupUser = securityGroupUsers.stream()
                    .filter(sgu -> StringUtils.equals(sgu.getSecurityGroupCode(), SchoolRoleEnum.SCH_CLS_TEACHER.toString()))
                    .findFirst();
            // 如果该老师已经是班上的任课老师不处理
            if (securityGroupUser.isPresent()) {
                return;
            }
        }
        //
        SecurityGroup securityGroup = securityGroupService.findSecurityGroupInOrgByCode(schoolId, SchoolRoleEnum.SCH_CLS_TEACHER.toString());
        securityGroupService.setupUsers(securityGroup.getId(), classId, Lists.newArrayList(newEmployeeId));
    }

    /**
     * 获取指定班级的班主任
     *
     * @param classId 班级ID
     * @return 教职工ID，如果该班级还未设置班主任则返回null
     */
    public Teacher findClassMasterByClass(long classId) {

        if (classId < 1) {
            throw null;
        }

        List<Teacher> classTeacherRelations = teacherRepository.findByClassIdAndTitle(classId,
                SchoolTitleEnum.CLS_MASTER.toString());

        if (Collections3.isEmpty(classTeacherRelations)) {
            return null;
        }

        return classTeacherRelations.get(0);
    }

    /**
     * 获取班级中所有的老师：班主任、任课老师
     *
     * @param classId 班级ID
     * @return
     */
    public List<Teacher> findTeacherByClass(long classId) {

        if (classId < 1) {
            return Lists.newArrayList();
        }

        return teacherRepository.findAllByClass(classId);
    }
}
